//! # Point
//!
//! 三国杀卡牌点数定义

/// 定义点数类型
#[derive(Debug, Clone, PartialEq)]
pub enum Point {
    /// 未知类型，一般表示出错
    Unknown,

    P1,
    P2,
    P3,
    P4,
    P5,
    P6,
    P7,
    P8,
    P9,
    P10,
    P11,
    P12,
    P13,
}

impl Default for Point {
    fn default() -> Self {
        Self::Unknown
    }
}

/// 打印 Point 字符串
impl std::fmt::Display for Point {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Point::P1 => "A",
                Point::P2 => "2",
                Point::P3 => "3",
                Point::P4 => "4",
                Point::P5 => "5",
                Point::P6 => "6",
                Point::P7 => "7",
                Point::P8 => "8",
                Point::P9 => "9",
                Point::P10 => "10",
                Point::P11 => "J",
                Point::P12 => "Q",
                Point::P13 => "K",
                Point::Unknown => "Unknown",
            }
        )
    }
}

impl From<i32> for Point {
    fn from(i: i32) -> Self {
        match i {
            1 => Point::P1,
            2 => Point::P2,
            3 => Point::P3,
            4 => Point::P4,
            5 => Point::P5,
            6 => Point::P6,
            7 => Point::P7,
            8 => Point::P8,
            9 => Point::P9,
            10 => Point::P10,
            11 => Point::P11,
            12 => Point::P12,
            13 => Point::P13,
            _ => Self::Unknown,
        }
    }
}

impl Into<i32> for Point {
    fn into(self) -> i32 {
        match self {
            Point::P1 => 1,
            Point::P2 => 2,
            Point::P3 => 3,
            Point::P4 => 4,
            Point::P5 => 5,
            Point::P6 => 6,
            Point::P7 => 7,
            Point::P8 => 9,
            Point::P9 => 9,
            Point::P10 => 10,
            Point::P11 => 11,
            Point::P12 => 12,
            Point::P13 => 13,
            Point::Unknown => 0,
        }
    }
}

impl TryFrom<&str> for Point {
    type Error = crate::ParseStrError;

    fn try_from(text: &str) -> Result<Point, Self::Error> {
        match text {
            "A" | "a" | "1" => Ok(Self::P1),
            "2" => Ok(Self::P2),
            "3" => Ok(Self::P3),
            "4" => Ok(Self::P4),
            "5" => Ok(Self::P5),
            "6" => Ok(Self::P6),
            "7" => Ok(Self::P7),
            "8" => Ok(Self::P8),
            "9" => Ok(Self::P9),
            "10" => Ok(Self::P10),
            "J" | "j" | "11" => Ok(Self::P11),
            "Q" | "q" | "12" => Ok(Self::P12),
            "K" | "k" | "13" => Ok(Self::P13),
            _ => Err(crate::ParseStrError::new(crate::ParseType::Point, text)),
        }
    }
}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn test_from_i32() {
        assert_eq!(Point::from(5), Point::P5);
        assert_eq!(Point::from(-1), Point::Unknown);
    }
}
